home *** CD-ROM | disk | FTP | other *** search
/ Aminet 40 / Aminet 40 (2000)(Schatztruhe)[!][Dec 2000].iso / Aminet / game / shoot / ADoomPPC_src.lha / ADoomPPC_src / amiga_sound.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-18  |  26.1 KB  |  984 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdarg.h>
  4. #include <string.h>
  5.  
  6. #include "amiga_macros.h"
  7.  
  8. #include <exec/exec.h>
  9. #include <dos/dos.h>
  10. #include <dos/exall.h>
  11. #include <graphics/scale.h>
  12. #include <graphics/gfxbase.h>
  13. #include <devices/audio.h>
  14.  
  15. #include <proto/exec.h>
  16. #include <proto/dos.h>
  17. #include <proto/graphics.h>
  18.  
  19. #include <clib/alib_protos.h>
  20.  
  21. #if defined(WARPUP) || defined(MORPHOS)
  22. #include <powerup/ppclib/interface.h>
  23. #endif
  24.  
  25. #ifdef WARPUP
  26. #include <powerpc/powerpc.h>
  27. #include <clib/powerpc_protos.h>
  28. #endif
  29.  
  30. #ifdef MORPHOS
  31. #include <emul/emulregs.h>
  32. #include <emul/emulinterface.h>
  33. #endif
  34.  
  35. /* #include <math.h> */
  36.  
  37. #include "z_zone.h"
  38.  
  39. #include "i_system.h"
  40. #include "i_sound.h"
  41. #include "m_argv.h"
  42. #include "m_misc.h"
  43. #include "w_wad.h"
  44.  
  45. #include "doomdef.h"
  46.  
  47.  
  48. void audio_cleanup(void);
  49.  
  50. // Any value of numChannels set
  51. // by the defaults code in M_misc is now clobbered by I_InitSound().
  52. // number of channels available for sound effects
  53.  
  54. extern int numChannels;
  55.  
  56. extern struct ExecBase *SysBase;
  57.  
  58. #ifndef __VBCC__
  59. #define    BeginIO(ioRequest)    _BeginIO(ioRequest)
  60.  
  61. #ifdef WARPUP
  62. INLINE void _BeginIO(struct IORequest *ioRequest)
  63. {
  64.     struct PPCArgs args;
  65.     args.PP_Code = (APTR) ioRequest->io_Device;
  66.     args.PP_Offset = (-30);
  67.     args.PP_Flags = 0;
  68.     args.PP_Stack = NULL;
  69.     args.PP_StackSize = 0;
  70.     args.PP_Regs[PPREG_A1] = (ULONG) ioRequest;
  71.     Run68K(&args);
  72. }
  73.  
  74. #elif defined(MORPHOS)
  75. INLINE void _BeginIO(struct IORequest *ioRequest)
  76. {
  77.     struct EmulCaos Caos;
  78.     Caos.reg_a1 = (ULONG) ioRequest;
  79.     Caos.reg_a6 = (ULONG) ioRequest->io_Device;
  80.     Caos.caos_Un.Offset = (-30);
  81.     (*MyEmulHandle->EmulCallOS)(&Caos);
  82. }
  83.  
  84. #else
  85. INLINE void
  86. _BeginIO(struct IORequest *ioRequest)
  87. {
  88. struct Caos    MyCaos;
  89.     MyCaos.M68kCacheMode    =    IF_CACHEFLUSHALL;
  90. //    MyCaos.M68kStart    =    NULL;
  91. //    MyCaos.M68kSize        =    0;
  92.     MyCaos.PPCCacheMode    =    IF_CACHEFLUSHALL;
  93. //    MyCaos.PPCStart        =    NULL;
  94. //    MyCaos.PPCSize        =    0;
  95.     MyCaos.a1        =(ULONG) ioRequest;
  96.     MyCaos.caos_Un.Offset    =    (-30);
  97.     MyCaos.a6        =(ULONG) ioRequest->io_Device;
  98.     PPCCallOS(&MyCaos);
  99. }
  100. #endif
  101. #endif
  102.  
  103. /*
  104. Replacement for the ppc.library function
  105. Yeah, I'm a lazy typer ;)
  106. */
  107. #ifdef WARPUP
  108. static INLINE ULONG PPCCallM68k(struct Caos *MyCaos)
  109. {
  110.     struct PPCArgs args;
  111.     args.PP_Code = (APTR)MyCaos->caos_Un.Offset;
  112.     args.PP_Offset = 0;
  113.     args.PP_Flags = 0;
  114.     args.PP_Stack = NULL;
  115.     args.PP_StackSize = 0;
  116.     args.PP_Regs[PPREG_D0] = MyCaos->d0;
  117.     args.PP_Regs[PPREG_D1] = MyCaos->d1;
  118.     args.PP_Regs[PPREG_D2] = MyCaos->d2;
  119.     args.PP_Regs[PPREG_D3] = MyCaos->d3;
  120.     args.PP_Regs[PPREG_D4] = MyCaos->d4;
  121.     args.PP_Regs[PPREG_D5] = MyCaos->d5;
  122.     args.PP_Regs[PPREG_D6] = MyCaos->d6;
  123.     args.PP_Regs[PPREG_D7] = MyCaos->d7;
  124.     args.PP_Regs[PPREG_A0] = MyCaos->a0;
  125.     args.PP_Regs[PPREG_A1] = MyCaos->a1;
  126.     args.PP_Regs[PPREG_A2] = MyCaos->a2;
  127.     args.PP_Regs[PPREG_A3] = MyCaos->a3;
  128.     args.PP_Regs[PPREG_A4] = MyCaos->a4;
  129.     args.PP_Regs[PPREG_A5] = MyCaos->a5;
  130.     Run68K(&args);
  131.  
  132.     return args.PP_Regs[PPREG_D0];
  133. }
  134. #endif
  135.  
  136. #ifdef MORPHOS
  137. static INLINE ULONG PPCCallM68k(struct Caos *MyCaos)
  138. {
  139.     struct EmulCaos Caos;
  140.     Caos.caos_Un.Offset = MyCaos->caos_Un.Offset;
  141.     Caos.reg_d0 = MyCaos->d0;
  142.     Caos.reg_d1 = MyCaos->d1;
  143.     Caos.reg_d2 = MyCaos->d2;
  144.     Caos.reg_d3 = MyCaos->d3;
  145.     Caos.reg_d4 = MyCaos->d4;
  146.     Caos.reg_d5 = MyCaos->d5;
  147.     Caos.reg_d6 = MyCaos->d6;
  148.     Caos.reg_d7 = MyCaos->d7;
  149.     Caos.reg_a0 = MyCaos->a0;
  150.     Caos.reg_a1 = MyCaos->a1;
  151.     Caos.reg_a2 = MyCaos->a2;
  152.     Caos.reg_a3 = MyCaos->a3;
  153.     Caos.reg_a4 = MyCaos->a4;
  154.     Caos.reg_a5 = MyCaos->a5;
  155.     return (ULONG)(*MyEmulHandle->EmulCallOS)(&Caos);
  156. }
  157. #endif
  158.  
  159. /**********************************************************************/
  160. #define MAXSFXVOICES    16   /* max number of Sound Effects with server */
  161. #define MAXNUMCHANNELS   4   /* max number of Amiga sound channels */
  162. #define CHIP_CACHE_SIZE 12   /* number of waveforms allowed in chipmem */
  163.  
  164. struct chip_cache_info {
  165.   int id;
  166.   ULONG age;
  167.   char *chip_data;
  168.   int len;
  169. };
  170.  
  171. struct channel_info {
  172.   struct MsgPort *audio_mp;
  173.   struct IOAudio *audio_io;
  174.   BOOL sound_in_progress;
  175. };
  176.  
  177. /**********************************************************************/
  178. // The actual lengths of all sound effects.
  179. static int lengths[NUMSFX];
  180.  
  181. static struct MsgPort *audio_mp = NULL;
  182. static struct IOAudio *audio_io = NULL;
  183. static BOOL audio_is_open = FALSE;
  184.  
  185. static struct channel_info channel_info[MAXNUMCHANNELS] = {
  186.   {NULL, NULL, FALSE},
  187.   {NULL, NULL, FALSE},
  188.   {NULL, NULL, FALSE},
  189.   {NULL, NULL, FALSE},
  190. };
  191.  
  192. /* cache up to CHIP_CACHE_SIZE sound effects in chipmem, rest in fastmem */
  193. static struct chip_cache_info chip_cache_info[CHIP_CACHE_SIZE] = {
  194.   {-1, 0, NULL, -1},
  195.   {-1, 0, NULL, -1},
  196.   {-1, 0, NULL, -1},
  197.   {-1, 0, NULL, -1},
  198.   {-1, 0, NULL, -1},
  199.   {-1, 0, NULL, -1},
  200.   {-1, 0, NULL, -1},
  201.   {-1, 0, NULL, -1},
  202.   {-1, 0, NULL, -1},
  203.   {-1, 0, NULL, -1},
  204.   {-1, 0, NULL, -1},
  205.   {-1, 0, NULL, -1}
  206. };
  207.  
  208. static ULONG age = 1;
  209. static UWORD period_table[256];
  210.  
  211. static int changepitch;
  212. /* sampling freq (Hz) for each pitch step when changepitch is TRUE
  213.    calculated from (2^((i-128)/64))*11025
  214.    I'm not sure if this is the right formula */
  215. static UWORD freqs[256] = {
  216.   2756, 2786, 2817, 2847, 2878, 2910, 2941, 2973,
  217.   3006, 3038, 3072, 3105, 3139, 3173, 3208, 3242,
  218.   3278, 3313, 3350, 3386, 3423, 3460, 3498, 3536,
  219.   3574, 3613, 3653, 3692, 3733, 3773, 3814, 3856,
  220.   3898, 3940, 3983, 4027, 4071, 4115, 4160, 4205,
  221.   4251, 4297, 4344, 4391, 4439, 4487, 4536, 4586,
  222.   4635, 4686, 4737, 4789, 4841, 4893, 4947, 5001,
  223.   5055, 5110, 5166, 5222, 5279, 5336, 5394, 5453,
  224.   5513, 5573, 5633, 5695, 5757, 5819, 5883, 5947,
  225.   6011, 6077, 6143, 6210, 6278, 6346, 6415, 6485,
  226.   6556, 6627, 6699, 6772, 6846, 6920, 6996, 7072,
  227.   7149, 7227, 7305, 7385, 7465, 7547, 7629, 7712,
  228.   7796, 7881, 7967, 8053, 8141, 8230, 8319, 8410,
  229.   8501, 8594, 8688, 8782, 8878, 8975, 9072, 9171,
  230.   9271, 9372, 9474, 9577, 9681, 9787, 9893, 10001,
  231.   10110, 10220, 10331, 10444, 10558, 10673, 10789, 10906,
  232.   11025, 11145, 11266, 11389, 11513, 11638, 11765, 11893,
  233.   12023, 12154, 12286, 12420, 12555, 12692, 12830, 12970,
  234.   13111, 13254, 13398, 13544, 13691, 13841, 13991, 14144,
  235.   14298, 14453, 14611, 14770, 14931, 15093, 15258, 15424,
  236.   15592, 15761, 15933, 16107, 16282, 16459, 16639, 16820,
  237.   17003, 17188, 17375, 17564, 17756, 17949, 18144, 18342,
  238.   18542, 18744, 18948, 19154, 19363, 19574, 19787, 20002,
  239.   20220, 20440, 20663, 20888, 21115, 21345, 21578, 21812,
  240.   22050, 22290, 22533, 22778, 23026, 23277, 23530, 23787,
  241.   24046, 24308, 24572, 24840, 25110, 25384, 25660, 25940,
  242.   26222, 26508, 26796, 27088, 27383, 27681, 27983, 28287,
  243.   28595, 28907, 29221, 29540, 29861, 30187, 30515, 30848,
  244.   31183, 31523, 31866, 32213, 32564, 32919, 33277, 33639,
  245.   34006, 34376, 34750, 35129, 35511, 35898, 36289, 36684,
  246.   37084, 37487, 37896, 38308, 38725, 39147, 39573, 40004,
  247.   40440, 40880, 41325, 41775, 42230, 42690, 43155, 43625
  248. };
  249.  
  250. /**********************************************************************/
  251.  
  252. static struct Library *DoomSndBase = NULL;
  253.  
  254. static INLINE void Sfx_SetVol(int vol)
  255. {
  256. struct Caos    MyCaos;
  257.     MyCaos.M68kCacheMode        =    IF_CACHEFLUSHNO;
  258. //    MyCaos.M68kStart        =    NULL;
  259. //    MyCaos.M68kSize            =    0;
  260.     MyCaos.PPCCacheMode        =    IF_CACHEFLUSHNO;
  261. //    MyCaos.PPCStart            =    NULL;
  262. //    MyCaos.PPCSize            =    0;
  263.     MyCaos.d0            =    vol;
  264.     MyCaos.caos_Un.Offset        =       (((int)DoomSndBase)-30);
  265.     PPCCallM68k(&MyCaos);
  266. }
  267.  
  268. static INLINE void Sfx_Start(char *wave, int cnum, int step, int vol, int sep, int length)
  269. {
  270. struct Caos    MyCaos;
  271.     MyCaos.M68kCacheMode        =    IF_CACHEFLUSHALL;
  272. //    MyCaos.M68kStart        =    NULL;
  273. //    MyCaos.M68kSize            =    0;
  274.     MyCaos.PPCCacheMode        =    IF_CACHEFLUSHALL;
  275. //    MyCaos.PPCStart            =    NULL;
  276. //    MyCaos.PPCSize            =    0;
  277.     MyCaos.a0            = (ULONG) wave;
  278.     MyCaos.d0            =    cnum;
  279.     MyCaos.d1            =    step;
  280.     MyCaos.d2            =    vol;
  281.     MyCaos.d3            =    sep;
  282.     MyCaos.d4            =    length;
  283.     MyCaos.caos_Un.Offset        =       (((int)DoomSndBase)-36);
  284.     PPCCallM68k(&MyCaos);
  285. }
  286.  
  287. static INLINE void Sfx_Update(int cnum, int step, int vol, int sep)
  288. {
  289. struct Caos    MyCaos;
  290.     MyCaos.M68kCacheMode        =    IF_CACHEFLUSHNO;
  291. //    MyCaos.M68kStart        =    NULL;
  292. //    MyCaos.M68kSize            =    0;
  293.     MyCaos.PPCCacheMode        =    IF_CACHEFLUSHNO;
  294. //    MyCaos.PPCStart            =    NULL;
  295. //    MyCaos.PPCSize            =    0;
  296.     MyCaos.d0            =    cnum;
  297.     MyCaos.d1            =    step;
  298.     MyCaos.d2            =    vol;
  299.     MyCaos.d3            =    sep;
  300.     MyCaos.caos_Un.Offset        =       (((int)DoomSndBase)-42);
  301.     PPCCallM68k(&MyCaos);
  302. }
  303.  
  304. static INLINE void Sfx_Stop(int cnum)
  305. {
  306. struct Caos    MyCaos;
  307.     MyCaos.M68kCacheMode        =    IF_CACHEFLUSHNO;
  308. //    MyCaos.M68kStart        =    NULL;
  309. //    MyCaos.M68kSize            =    0;
  310.     MyCaos.PPCCacheMode        =    IF_CACHEFLUSHNO;
  311. //    MyCaos.PPCStart            =    NULL;
  312. //    MyCaos.PPCSize            =    0;
  313.     MyCaos.d0            =    cnum;
  314.     MyCaos.caos_Un.Offset        =       (((int)DoomSndBase)-48);
  315.     PPCCallM68k(&MyCaos);
  316. }
  317.  
  318. static INLINE int Sfx_Done(int cnum)
  319. {
  320. struct Caos    MyCaos;
  321.     MyCaos.M68kCacheMode        =    IF_CACHEFLUSHNO;
  322. //    MyCaos.M68kStart        =    NULL;
  323. //    MyCaos.M68kSize            =    0;
  324.     MyCaos.PPCCacheMode        =    IF_CACHEFLUSHNO;
  325. //    MyCaos.PPCStart            =    NULL;
  326. //    MyCaos.PPCSize            =    0;
  327.     MyCaos.d0            =    cnum;
  328.     MyCaos.caos_Un.Offset        =       (((int)DoomSndBase)-54);
  329.     return((int)PPCCallM68k(&MyCaos));
  330. }
  331.  
  332. static INLINE void Mus_SetVol(int vol)
  333. {
  334. struct Caos    MyCaos;
  335.     MyCaos.M68kCacheMode        =    IF_CACHEFLUSHNO;
  336. //    MyCaos.M68kStart        =    NULL;
  337. //    MyCaos.M68kSize            =    0;
  338.     MyCaos.PPCCacheMode        =    IF_CACHEFLUSHNO;
  339. //    MyCaos.PPCStart            =    NULL;
  340. //    MyCaos.PPCSize            =    0;
  341.     MyCaos.d0            =    vol;
  342.     MyCaos.caos_Un.Offset        =       (((int)DoomSndBase)-60);
  343.     PPCCallM68k(&MyCaos);
  344. }
  345.  
  346. static INLINE int Mus_Register(void *musdata)
  347. {
  348. struct Caos    MyCaos;
  349.     MyCaos.M68kCacheMode        =    IF_CACHEFLUSHALL;
  350. //    MyCaos.M68kStart        =    NULL;
  351. //    MyCaos.M68kSize            =    0;
  352.     MyCaos.PPCCacheMode        =    IF_CACHEFLUSHALL;
  353. //    MyCaos.PPCStart            =    NULL;
  354. //    MyCaos.PPCSize            =    0;
  355.     MyCaos.a0            = (ULONG) musdata;
  356.     MyCaos.caos_Un.Offset        =       (((int)DoomSndBase)-66);
  357.     return((int)PPCCallM68k(&MyCaos));
  358. }
  359.  
  360. static INLINE void Mus_Unregister(int handle)
  361. {
  362. struct Caos    MyCaos;
  363.     MyCaos.M68kCacheMode        =    IF_CACHEFLUSHNO;
  364. //    MyCaos.M68kStart        =    NULL;
  365. //    MyCaos.M68kSize            =    0;
  366.     MyCaos.PPCCacheMode        =    IF_CACHEFLUSHNO;
  367. //    MyCaos.PPCStart            =    NULL;
  368. //    MyCaos.PPCSize            =    0;
  369.     MyCaos.d0            =    handle;
  370.     MyCaos.caos_Un.Offset        =       (((int)DoomSndBase)-72);
  371.     PPCCallM68k(&MyCaos);
  372. }
  373.  
  374. static INLINE void Mus_Play(int handle, int looping)
  375. {
  376. struct Caos    MyCaos;
  377.     MyCaos.M68kCacheMode        =    IF_CACHEFLUSHNO;
  378. //    MyCaos.M68kStart        =    NULL;
  379. //    MyCaos.M68kSize            =    0;
  380.     MyCaos.PPCCacheMode        =    IF_CACHEFLUSHNO;
  381. //    MyCaos.PPCStart            =    NULL;
  382. //    MyCaos.PPCSize            =    0;
  383.     MyCaos.d0            =    handle;
  384.     MyCaos.d1            =    looping;
  385.     MyCaos.caos_Un.Offset        =       (((int)DoomSndBase)-78);
  386.     PPCCallM68k(&MyCaos);
  387. }
  388.  
  389. static INLINE void Mus_Stop(int handle)
  390. {
  391. struct Caos    MyCaos;
  392.     MyCaos.M68kCacheMode        =    IF_CACHEFLUSHNO;
  393. //    MyCaos.M68kStart        =    NULL;
  394. //    MyCaos.M68kSize            =    0;
  395.     MyCaos.PPCCacheMode        =    IF_CACHEFLUSHNO;
  396. //    MyCaos.PPCStart            =    NULL;
  397. //    MyCaos.PPCSize            =    0;
  398.     MyCaos.d0            =    handle;
  399.     MyCaos.caos_Un.Offset        =       (((int)DoomSndBase)-84);
  400.     PPCCallM68k(&MyCaos);
  401. }
  402.  
  403. static INLINE void Mus_Pause(int handle)
  404. {
  405. struct Caos    MyCaos;
  406.     MyCaos.M68kCacheMode        =    IF_CACHEFLUSHNO;
  407. //    MyCaos.M68kStart        =    NULL;
  408. //    MyCaos.M68kSize            =    0;
  409.     MyCaos.PPCCacheMode        =    IF_CACHEFLUSHNO;
  410. //    MyCaos.PPCStart            =    NULL;
  411. //    MyCaos.PPCSize            =    0;
  412.     MyCaos.d0            =    handle;
  413.     MyCaos.caos_Un.Offset        =       (((int)DoomSndBase)-90);
  414.     PPCCallM68k(&MyCaos);
  415. }
  416.  
  417. static INLINE void Mus_Resume(int handle)
  418. {
  419. struct Caos    MyCaos;
  420.     MyCaos.M68kCacheMode        =    IF_CACHEFLUSHNO;
  421. //    MyCaos.M68kStart        =    NULL;
  422. //    MyCaos.M68kSize            =    0;
  423.     MyCaos.PPCCacheMode        =    IF_CACHEFLUSHNO;
  424. //    MyCaos.PPCStart            =    NULL;
  425. //    MyCaos.PPCSize            =    0;
  426.     MyCaos.d0            =    handle;
  427.     MyCaos.caos_Un.Offset        =       (((int)DoomSndBase)-96);
  428.     PPCCallM68k(&MyCaos);
  429. }
  430.  
  431. static INLINE int MUS_Done(int handle)
  432. {
  433. struct Caos    MyCaos;
  434.     MyCaos.M68kCacheMode        =    IF_CACHEFLUSHNO;
  435. //    MyCaos.M68kStart        =    NULL;
  436. //    MyCaos.M68kSize            =    0;
  437.     MyCaos.PPCCacheMode        =    IF_CACHEFLUSHNO;
  438. //    MyCaos.PPCStart            =    NULL;
  439. //    MyCaos.PPCSize            =    0;
  440.     MyCaos.d0            =    handle;
  441.     MyCaos.caos_Un.Offset        =       (((int)DoomSndBase)-102);
  442.     return((int)PPCCallM68k(&MyCaos));
  443. }
  444.  
  445.  
  446. /**********************************************************************/
  447. //
  448. // This function loads the sound data for sfxname from the WAD lump,
  449. // and returns a ptr to the data in fastmem and its length in len.
  450. //
  451. static void *getsfx (char *sfxname, int *len)
  452. {
  453.   unsigned char*      sfx;
  454.   unsigned char*      paddedsfx;
  455.   int                 i;
  456.   int                 size;
  457. //  int                 paddedsize;
  458.   char                name[20];
  459.   int                 sfxlump;
  460.  
  461.   // Get the sound data from the WAD, allocate lump
  462.   //  in zone memory.
  463.   sprintf(name, "ds%s", sfxname);
  464.  
  465.   // Now, there is a severe problem with the
  466.   //  sound handling, in it is not (yet/anymore)
  467.   //  gamemode aware. That means, sounds from
  468.   //  DOOM II will be requested even with DOOM
  469.   //  shareware.
  470.   // The sound list is wired into sounds.c,
  471.   //  which sets the external variable.
  472.   // I do not do runtime patches to that
  473.   //  variable. Instead, we will use a
  474.   //  default sound for replacement.
  475.   if (W_CheckNumForName(name) == -1)
  476.     sfxlump = W_GetNumForName("dspistol");
  477.   else
  478.     sfxlump = W_GetNumForName (name);
  479.  
  480.   size = W_LumpLength (sfxlump);
  481.  
  482.   // Debug.
  483.   // fprintf( stderr, "." );
  484.   // fprintf( stderr, " -loading  %s (lump %d, %d bytes)\n",
  485.   //         sfxname, sfxlump, size );
  486.   //fflush( stderr );
  487.  
  488.   sfx = (unsigned char*)W_CacheLumpNum (sfxlump, PU_STATIC);
  489.  
  490.   // Allocate from zone memory.
  491.   paddedsfx = (unsigned char*)Z_Malloc (size, PU_STATIC, 0);
  492.   // ddt: (unsigned char *) realloc(sfx, paddedsize+8);
  493.   // This should interfere with zone memory handling,
  494.   //  which does not kick in in the soundserver.
  495.  
  496.   // Now copy and pad.
  497.   for (i = 0; i < size; i++)
  498.     paddedsfx[i] = sfx[i] ^ 0x80;
  499.   /* memcpy (paddedsfx, sfx, size); */
  500.  
  501.   // Remove the cached lump.
  502.   Z_Free( sfx );
  503.  
  504.   // Preserve padded length.
  505.   *len = size;
  506.  
  507.   // Return allocated padded data.
  508.   return (void *) (paddedsfx /* + 8 */);
  509. }
  510.  
  511. /**********************************************************************/
  512. // Init at program start...
  513. void I_InitSound (void)
  514. {
  515.   int i;
  516.   struct channel_info *c;
  517.   UBYTE chans[1];
  518.   ULONG clock_constant;   /* see Amiga Hardware Manual page 141 */
  519.  
  520.     atexit(audio_cleanup);
  521.  
  522.   if (M_CheckParm("-nosfx"))
  523.     return;
  524.  
  525.   // Secure and configure sound device first.
  526.   fprintf( stderr, "I_InitSound: ");
  527.     fflush(stderr);
  528.  
  529.   if ((DoomSndBase = OpenLibrary ("doomsound.library",37)) != NULL) {
  530.     Sfx_SetVol(64);
  531.     Mus_SetVol(64);
  532.     numChannels = 16;
  533.   } else {
  534.     fprintf (stderr, " Cannot open doomsound.library, music not available.\n" );
  535.     fprintf( stderr, "I_InitSound: ");
  536.         fflush(stderr);
  537.   }
  538.  
  539.   if (DoomSndBase == NULL) {
  540.     numChannels = 4;
  541.  
  542.     if ((audio_mp = CreateMsgPort ()) == NULL ||
  543.         (audio_io = (struct IOAudio *)AllocMem(sizeof(struct IOAudio),
  544.                                              MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  545.       I_Error ("CreateMsgPort() or AllocMem() failed");
  546.  
  547.     chans[0] = (1 << numChannels) - 1; /* numchannels Amiga audio channels */
  548.     audio_io->ioa_Request.io_Message.mn_ReplyPort = audio_mp;
  549.     audio_io->ioa_Request.io_Message.mn_Node.ln_Pri = 127;
  550.     audio_io->ioa_AllocKey = 0;
  551.     audio_io->ioa_Data = chans;
  552.     audio_io->ioa_Length = sizeof(chans);
  553.  
  554.     if (OpenDevice (AUDIONAME, 0, (struct IORequest *)audio_io, 0) != 0)
  555.       I_Error ("OpenDevice(\"audio.device\") failed");
  556.     audio_is_open = TRUE;
  557.  
  558.     for (i = 0; i < numChannels; i++) {
  559.       c = &channel_info[i];
  560.       if ((c->audio_mp = CreateMsgPort ()) == NULL ||
  561.           (c->audio_io = (struct IOAudio *)AllocMem(sizeof(struct IOAudio),
  562.                                              MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  563.         I_Error ("CreateMsgPort() or AllocMem() failed");
  564.       *c->audio_io = *audio_io;
  565.       c->audio_io->ioa_Request.io_Message.mn_ReplyPort = c->audio_mp;
  566.       c->audio_io->ioa_Request.io_Unit = (struct Unit *)(1 << i);
  567.     }
  568.   }
  569.  
  570.   if ((GfxBase->DisplayFlags & REALLY_PAL) == 0)
  571.     clock_constant = 3579545;   /* NTSC */
  572.   else
  573.     clock_constant = 3546895;   /* PAL */
  574.   changepitch = M_CheckParm ("-changepitch");
  575.   for (i = 0; i < 256; i++) {
  576.     if (changepitch)
  577.       period_table[i] = ((clock_constant << 1) + freqs[i]) /
  578.                         (((ULONG)freqs[i]) << 1);
  579.     else
  580.       period_table[i] = ((clock_constant << 1) + 11025) / ((11025) << 1);
  581.   }
  582.  
  583.   fprintf (stderr, " configured audio device\n" );
  584.     fflush(stderr);
  585.  
  586.   // Initialize external data (all sounds) at start, keep static.
  587.   fprintf (stderr, "I_InitSound: ");
  588.     fflush(stderr);
  589.  
  590.   for (i = 1; i < NUMSFX; i++) {
  591.     // Alias? Example is the chaingun sound linked to pistol.
  592.     if (!S_sfx[i].link) {
  593.       // Load data from WAD file.
  594.       S_sfx[i].data = getsfx (S_sfx[i].name, &lengths[i]);
  595.     } else {
  596.       // Previously loaded already?
  597.       S_sfx[i].data = S_sfx[i].link->data;
  598.       lengths[i] = lengths[(S_sfx[i].link - S_sfx)/sizeof(sfxinfo_t)];
  599.     }
  600.   }
  601.  
  602.   fprintf (stderr, " pre-cached all sound data\n");
  603.     fflush(stderr);
  604.  
  605.   // Finished initialization.
  606.   fprintf (stderr, "I_InitSound: sound module ready\n");
  607.     fflush(stderr);
  608. }
  609.  
  610. /**********************************************************************/
  611. // ... update sound buffer and audio device at runtime...
  612. void I_UpdateSound (void)
  613. {
  614.   /* fprintf (stderr, "I_UpdateSound()\n"); */
  615. }
  616.  
  617. /**********************************************************************/
  618. // ... update sound buffer and audio device at runtime...
  619. void I_SubmitSound (void)
  620. {
  621.   /* fprintf (stderr, "I_SubmitSound()\n"); */
  622.   // Write it to DSP device.
  623.   // write(audio_fd, mixbuffer, SAMPLECOUNT*BUFMUL);
  624. }
  625.  
  626. /**********************************************************************/
  627. // ... shut down and relase at program termination.
  628. void I_ShutdownSound (void)
  629. {
  630.   int i;
  631.  
  632.   fprintf (stderr, "I_ShutdownSound()\n");
  633.     fflush (stderr);
  634.  
  635.   if (DoomSndBase != NULL) {
  636.     CloseLibrary (DoomSndBase);
  637.     DoomSndBase = NULL;
  638.   }
  639.  
  640.   if (audio_is_open) {
  641.     for (i = 0; i < numChannels; i++)
  642.       I_StopSound (i);
  643.     audio_io->ioa_Request.io_Unit = (struct Unit *)
  644.                      ((1 << numChannels) - 1);  /* free numChannels channels */
  645.     CloseDevice ((struct IORequest *)audio_io);
  646.     audio_is_open = FALSE;
  647.   }
  648.   for (i = 0; i < CHIP_CACHE_SIZE; i++) {
  649.     if (chip_cache_info[i].chip_data != NULL) {
  650.       FreeMem (chip_cache_info[i].chip_data, chip_cache_info[i].len);
  651.       chip_cache_info[i].chip_data = NULL;
  652.     }
  653.   }
  654.   for (i = 0; i < MAXNUMCHANNELS; i++) {
  655.     if (channel_info[i].audio_io != NULL) {
  656.       FreeMem (channel_info[i].audio_io, sizeof(struct IOAudio));
  657.       channel_info[i].audio_io = NULL;
  658.     }
  659.     if (channel_info[i].audio_mp != NULL) {
  660.       DeleteMsgPort (channel_info[i].audio_mp);
  661.       channel_info[i].audio_mp = NULL;
  662.     }
  663.   }
  664.   if (audio_io != NULL) {
  665.     FreeMem (audio_io, sizeof(struct IOAudio));
  666.     audio_io = NULL;
  667.   }
  668.   if (audio_mp != NULL) {
  669.     DeleteMsgPort (audio_mp);
  670.     audio_mp = NULL;
  671.   }
  672. }
  673.  
  674. /**********************************************************************/
  675. /**********************************************************************/
  676. //
  677. //  SFX I/O
  678. //
  679.  
  680. /**********************************************************************/
  681. // Initialize number of channels
  682. void I_SetChannels (void)
  683. {
  684. }
  685.  
  686. /**********************************************************************/
  687. // Get raw data lump index for sound descriptor.
  688. int I_GetSfxLumpNum (sfxinfo_t *sfx)
  689. {
  690.   char namebuf[9];
  691.  
  692.   /* fprintf (stderr, "I_GetSfxLumpNum()\n"); */
  693.   sprintf(namebuf, "ds%s", sfx->name);
  694.   return W_GetNumForName(namebuf);
  695. }
  696.  
  697. /**********************************************************************/
  698. // Find chip cache entry used longest ago and re-use it.
  699. static int cache_chip_data (int id)
  700. {
  701.   int i, mini;
  702.   ULONG minage;
  703.   struct chip_cache_info *c;
  704.  
  705.   if (age == 0xfffffffe)
  706.     I_Error ("Age overflow in cache_chip_data()");
  707.   minage = 0xffffffff;
  708.   mini = 0;
  709.   for (i = 0; i < CHIP_CACHE_SIZE; i++) {
  710.     c = &chip_cache_info[i];
  711.     if (c->id == id) {
  712.       c->age = age++;
  713.       return i;
  714.     }
  715.     if (c->age < minage) {
  716.       minage = c->age;
  717.       mini = i;
  718.     }
  719.   }
  720.   c = &chip_cache_info[mini];
  721.   if (c->chip_data != NULL) {
  722.     FreeMem (c->chip_data, c->len);
  723.     c->chip_data = NULL;
  724.   }
  725.   c->id = id;
  726.   c->age = age++;
  727.   if ((c->chip_data = AllocMem (lengths[id], MEMF_CHIP)) == NULL)
  728.     I_Error ("Out of CHIP memory allocating %d bytes", lengths[id]);
  729. //  memcpy (c->chip_data, S_sfx[id].data, lengths[id]);
  730.   CopyMem (S_sfx[id].data, c->chip_data, lengths[id]);
  731.   c->len = lengths[id];
  732.   return mini;
  733. }
  734.  
  735. /**********************************************************************/
  736. // Starts a sound in a particular sound channel.
  737. int I_StartSound (
  738.   int id,
  739.   int cnum,
  740.   int vol,
  741.   int sep,
  742.   int pitch,
  743.   int priority )
  744. {
  745.   struct channel_info *c;
  746.  
  747. /*  fprintf (stderr, "I_StartSound(%d,%d,%d,%d,%d,%d)\n", id, cnum, vol, sep,
  748.               pitch, priority); */
  749.  
  750.   if (DoomSndBase != NULL) {
  751.     I_StopSound(cnum);
  752.     Sfx_Start (S_sfx[id].data, cnum, changepitch ? freqs[pitch] : 11025,
  753.                vol<<3, sep, lengths[id]);
  754.     return cnum;
  755.   }
  756.  
  757.   if (!audio_is_open)
  758.     return 1;
  759.   I_StopSound (cnum);
  760.   c = &channel_info[cnum];
  761.   c->audio_io->ioa_Request.io_Command = CMD_WRITE;
  762.   c->audio_io->ioa_Request.io_Flags = ADIOF_PERVOL;
  763.   c->audio_io->ioa_Data = &chip_cache_info[cache_chip_data (id)].chip_data[8];
  764.   c->audio_io->ioa_Length = lengths[id] - 8;
  765.   c->audio_io->ioa_Period = period_table[pitch];
  766.   c->audio_io->ioa_Volume = vol << 2;
  767.   c->audio_io->ioa_Cycles = 1;
  768.   BeginIO ((struct IORequest *)c->audio_io);
  769.   c->sound_in_progress = TRUE;
  770.   return cnum;
  771. }
  772.  
  773. /**********************************************************************/
  774. // Stops a sound channel.
  775. void I_StopSound(int handle)
  776. {
  777.   /* fprintf (stderr, "I_StopSound(%d)\n", handle); */
  778.  
  779.   if (DoomSndBase != NULL) {
  780.     Sfx_Stop(handle);
  781.     return;
  782.   }
  783.  
  784.   if (!audio_is_open)
  785.     return;
  786.   if (channel_info[handle].sound_in_progress) {
  787.     AbortIO ((struct IORequest *)channel_info[handle].audio_io);
  788.     WaitPort (channel_info[handle].audio_mp);
  789.     GetMsg (channel_info[handle].audio_mp);
  790.     channel_info[handle].sound_in_progress = FALSE;
  791.   }
  792. }
  793.  
  794. /**********************************************************************/
  795. // Called by S_*() functions
  796. //  to see if a channel is still playing.
  797. // Returns 0 if no longer playing, 1 if playing.
  798. int I_SoundIsPlaying(int handle)
  799. {
  800.   /* fprintf (stderr, "I_SoundIsPlaying(%d)\n", handle); */
  801.  
  802.   if (DoomSndBase != NULL) {
  803.     return Sfx_Done(handle) ? 1 : 0;
  804.   }
  805.  
  806.   if (!audio_is_open)
  807.     return 0;
  808.   if (channel_info[handle].sound_in_progress) {
  809.     if (CheckIO ((struct IORequest *)channel_info[handle].audio_io)) {
  810.       WaitPort (channel_info[handle].audio_mp);  /* clears signal & returns immediately */
  811.       GetMsg (channel_info[handle].audio_mp);
  812.       channel_info[handle].sound_in_progress = FALSE;
  813.       return 0;
  814.     } else {
  815.       return 1;
  816.     }
  817.   }
  818.   return 0;
  819. }
  820.  
  821. /**********************************************************************/
  822. // Updates the volume, separation,
  823. //  and pitch of a sound channel.
  824. void
  825. I_UpdateSoundParams
  826. ( int        handle,
  827.   int        vol,
  828.   int        sep,
  829.   int        pitch )
  830. {
  831. /*
  832.   fprintf (stderr, "I_UpdateSoundParams(%d,%d,%d,%d)\n", handle, vol,
  833.            sep, pitch);
  834. */
  835.  
  836.   if (DoomSndBase != NULL) {
  837.     Sfx_Update(handle, changepitch ? freqs[pitch] : 11025, vol<<3, sep);
  838.     return;
  839.   }
  840.  
  841.   if (!audio_is_open)
  842.     return;
  843.   if (channel_info[handle].sound_in_progress) {
  844.     audio_io->ioa_Request.io_Command = ADCMD_PERVOL;
  845.     audio_io->ioa_Request.io_Flags = ADIOF_PERVOL;
  846.     audio_io->ioa_Request.io_Unit = (struct Unit *)(1 << handle);
  847.     audio_io->ioa_Period = period_table[pitch];
  848.     audio_io->ioa_Volume = vol << 2;
  849.     BeginIO ((struct IORequest *)audio_io);
  850.     WaitPort (audio_mp);
  851.     GetMsg (audio_mp);
  852.   }
  853. }
  854.  
  855.  
  856. /**********************************************************************/
  857. /**********************************************************************/
  858. //
  859. // MUSIC API.
  860. //
  861.  
  862. //static int looping=0;
  863. static int musicdies=-1;
  864.  
  865. static int music_okay = 0;
  866.  
  867. /**********************************************************************/
  868. //
  869. //  MUSIC I/O
  870. //
  871. void I_InitMusic(void)
  872. {
  873. //  fprintf (stderr, "I_InitMusic()\n");
  874.  
  875.   if (M_CheckParm("-music") && (DoomSndBase != NULL))
  876.     music_okay = 1;
  877. }
  878.  
  879. /**********************************************************************/
  880. void I_ShutdownMusic(void)
  881. {
  882. //  fprintf (stderr, "I_ShutdownMusic()\n");
  883. }
  884.  
  885. /**********************************************************************/
  886. // Volume.
  887. void I_SetMusicVolume(int volume)
  888. {
  889. //  fprintf (stderr, "I_SetMusicVolume(%d)\n", volume);
  890.   snd_MusicVolume = volume;
  891.  
  892.   if (music_okay) {
  893.     Mus_SetVol((volume<<2)+4);
  894.   }
  895. }
  896.  
  897. /**********************************************************************/
  898. // PAUSE game handling.
  899. void I_PauseSong(int handle)
  900. {
  901. //  fprintf (stderr, "I_PauseSong(%d)\n", handle);
  902.  
  903.   if (music_okay) {
  904.     Mus_Pause(handle);
  905.   }
  906. }
  907.  
  908. /**********************************************************************/
  909. void I_ResumeSong(int handle)
  910. {
  911. //  fprintf (stderr, "I_ResumeSong(%d)\n", handle);
  912.  
  913.   if (music_okay) {
  914.     Mus_Resume(handle);
  915.   }
  916. }
  917.  
  918. /**********************************************************************/
  919. // Registers a song handle to song data.
  920. int I_RegisterSong(void *data)
  921. {
  922. //  fprintf (stderr, "I_RegisterSong(%08x)\n", data);
  923.  
  924.   if (music_okay) {
  925.     return Mus_Register(data);
  926.   } else
  927.     return 2;
  928. }
  929.  
  930. /**********************************************************************/
  931. // Called by anything that wishes to start music.
  932. //  plays a song, and when the song is done,
  933. //  starts playing it again in an endless loop.
  934. // Horrible thing to do, considering.
  935. void
  936. I_PlaySong
  937. ( int        handle,
  938.   int        looping )
  939. {
  940. //  fprintf (stderr, "I_PlaySong(%d,%d)\n", handle, looping);
  941.  
  942.   if (music_okay) {
  943.     Mus_Play(handle, looping);
  944.   }
  945.  
  946.   musicdies = gametic + TICRATE*30;
  947. }
  948.  
  949. /**********************************************************************/
  950. // Stops a song over 3 seconds.
  951. void I_StopSong(int handle)
  952. {
  953. //  fprintf (stderr, "I_StopSong(%d)\n", handle);
  954.  
  955.   if (music_okay) {
  956.     Mus_Stop(handle);
  957.   }
  958.   musicdies = 0;
  959. }
  960.  
  961. /**********************************************************************/
  962. // See above (register), then think backwards
  963. void I_UnRegisterSong(int handle)
  964. {
  965. //  fprintf (stderr, "I_UnRegisterSong(%d)\n", handle);
  966.  
  967.   if (music_okay) {
  968.     Mus_Unregister(handle);
  969.   }
  970.   handle = 0;
  971. }
  972.  
  973. /**********************************************************************/
  974.  
  975.  
  976. /**********************************************************************/
  977. void audio_cleanup (void)
  978. {
  979.   I_ShutdownSound ();
  980.   I_ShutdownMusic ();
  981. }
  982.  
  983. /**********************************************************************/
  984.